package pushserver

import (
	"fmt"
	"net"
	"pushserver/connpool"
	"pushserver/filter"
)

type Listenter struct {
	net.Listener
	pool connpool.Pool
	// tcp代理类
	tcpProxy *TcpProxy
	// 有客户端上线时
	onConnect func(string)
	//过滤器
	Filter filter.Filter
	// 身份验证
	OnAuthentication func(string) (string, error)
}

// 初始化一个监听器
func NewListener(pool connpool.Pool, proxy *TcpProxy) *Listenter {
	this := &Listenter{}
	this.pool = pool
	this.tcpProxy = proxy
	return this
}

// 开启监听（阻塞）
func (this *Listenter) Listen(addr string) {
	lsten, err := net.Listen("tcp", addr)
	if err != nil {
		panic(err)
	}
	fmt.Printf("listen address %s ....\n", addr)
	for {
		conn, err := lsten.Accept()
		if err == nil {
			go func() {
				this.handler(conn)
			}()
		}
	}
}
func (this *Listenter) OnlineCount() int {
	return this.pool.Count()
}

func (this *Listenter) handler(conn net.Conn) {
	//过滤器
	if this.Filter != nil {
		if b := this.Filter.Filter(conn); !b {
			this.closeConn(conn, nil)
			return
		}
	}
	//SSL
	if err := this.tcpProxy.SSL(conn); err != nil {
		this.closeConn(conn, err)
		return
	}
	var connID string
	if this.OnAuthentication != nil {
		buffer, err := this.tcpProxy.Read(conn)
		if err != nil {
			this.closeConn(conn, err)
			return
		}
		readStr := string(<-buffer)
		if connID, err = this.OnAuthentication(readStr); err != nil {
			this.closeConn(conn, err)
			return
		}
	}
	if connID == "" {
		connID = fmt.Sprintf("conn %s", conn.RemoteAddr().String())
	}
	if this.onConnect != nil {
		this.onConnect(connID)
	}
	this.pool.Put(connID, conn)
}

func (this *Listenter) closeConn(conn net.Conn, err error) {
	defer conn.Close()
	var errStr string
	if err == nil {
		errStr = "close connect by remote server"
	} else {
		errStr = fmt.Sprint(err)
	}
	conn.Write([]byte(errStr))
}
